﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using XamlaApp.ViewModels;
using XamlaApp.Interfaces;
namespace XamlaApp.Views.UIViews
{
    public partial class ControlEditorHandle : UserControl, IDraggable, IXamlaElement
    {
        public FrameworkElementViewModel VM { get; set; }
        private FrameworkElementViewModel _controlVM { get; set; }
        private Action _positionAction;
        private Action _dragAction;
        private bool _isDragging;
        private Rect _originalControlDimensions;
        private Point _originalHandleLocation;

        public ControlEditorHandle(FrameworkElementViewModel controlViewModel, ControlHandleTypes handleType)
        {
            AssignHandleType(handleType);
            DataContext = VM = new FrameworkElementViewModel();

            VM.RegisterPositionBoundElement(this);
            _controlVM = controlViewModel;
            _controlVM.PropertyChanged += _controlVM_PropertyChanged;

            _positionAction();

            InitializeComponent();
        }

        private void AssignHandleType(ControlHandleTypes handleType)
        {
            //set the position action for this HandleType
            switch (handleType)
            {
                case ControlHandleTypes.TopLeft:
                    _positionAction = DoPositionTopLeftAction;
                    _dragAction = DoTopLeftDragAction;
                    break;
                case ControlHandleTypes.Top:
                    _positionAction = DoPositionTopAction;
                    _dragAction = DoTopDragAction;
                    break;
                case ControlHandleTypes.TopRight:
                    _positionAction = DoPositionTopRightAction;
                    _dragAction = DoTopRightDragAction;
                    break;
                case ControlHandleTypes.Right:
                    _positionAction = DoPositionRightAction;
                    _dragAction = DoRightDragAction;
                    break;
                case ControlHandleTypes.BottomRight:
                    _positionAction = DoPositionBottomRightAction;
                    _dragAction = DoBottomRightDragAction;
                    break;
                case ControlHandleTypes.Bottom:
                    _positionAction = DoPositionBottomAction;
                    _dragAction = DoBottomDragAction;
                    break;
                case ControlHandleTypes.BottomLeft:
                    _positionAction = DoPositionBottomLeftAction;
                    _dragAction = DoBottomLeftDragAction;
                    break;
                case ControlHandleTypes.Left:
                    _positionAction = DoPositionLeftAction;
                    _dragAction = DoLeftDragAction;
                    break;

            }
        }

        private void UpdateOriginalDimensions()
        {
            _originalControlDimensions = new Rect(_controlVM.Left, _controlVM.Top, _controlVM.Width, _controlVM.Height);
            _originalHandleLocation = new Point(VM.Left, VM.Top);
        }

        void _controlVM_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            //here we are going to catch view model changes to the element control and adjust our handle position accordingly
            switch (e.PropertyName)
            {
                case "Left":
                case "Top":
                case "Width":
                case "Height":
                    //update position unless we are dragging with this control, in which case the dragging updates will handle position changes
                    if (_positionAction != null && !_isDragging) _positionAction();
                    break;
            }
        }

        #region HandleType Position Actions
        void DoPositionTopLeftAction()
        {
            VM.Left = _controlVM.Left - 10;
            VM.Top = _controlVM.Top - 10;
        }
        void DoPositionTopAction()
        {
            VM.Left = _controlVM.Left + (_controlVM.Width / 2) - 5;
            VM.Top = _controlVM.Top - 11;
        }
        void DoPositionTopRightAction()
        {
            VM.Left = _controlVM.Left + _controlVM.Width;
            VM.Top = _controlVM.Top - 11;
        }
        void DoPositionRightAction()
        {
            VM.Left = _controlVM.Left + (_controlVM.Width);
            VM.Top = _controlVM.Top + (_controlVM.Height / 2) - 5;
        }
        void DoPositionBottomRightAction()
        {
            VM.Left = _controlVM.Left + _controlVM.Width;
            VM.Top = _controlVM.Top + _controlVM.Height;
        }
        void DoPositionBottomAction()
        {
            VM.Left = _controlVM.Left + (_controlVM.Width / 2) - 5;
            VM.Top = _controlVM.Top + _controlVM.Height;
        }
        void DoPositionBottomLeftAction()
        {
            VM.Left = _controlVM.Left - 10;
            VM.Top = _controlVM.Top + _controlVM.Height;
        }
        void DoPositionLeftAction()
        {
            VM.Left = _controlVM.Left - 10;
            VM.Top = _controlVM.Top + (_controlVM.Height / 2) - 5;
        }

        #endregion

        #region Drag Actions
        void DoTopLeftDragAction()
        {
            _controlVM.Top = VM.Top;
            _controlVM.Left = VM.Left + 10;
            _controlVM.Width = _originalControlDimensions.Width + _originalControlDimensions.Left - VM.Left - 10;
            _controlVM.Height = _originalControlDimensions.Height + _originalControlDimensions.Top - VM.Top;
            //UpdateOriginalDimensions();

        }
        void DoTopDragAction()
        {
            _controlVM.Top = VM.Top + 10;
            _controlVM.Height = _originalControlDimensions.Height + _originalControlDimensions.Top - VM.Top - 10;
        }
        void DoTopRightDragAction()
        {
            _controlVM.Top = VM.Top + 10;
            _controlVM.Height = _originalControlDimensions.Height + _originalControlDimensions.Top - VM.Top - 10;
            _controlVM.Width = _originalControlDimensions.Width - (_originalHandleLocation.X - VM.Left);
        }
        void DoRightDragAction()
        {
            _controlVM.Width = _originalControlDimensions.Width - (_originalHandleLocation.X - VM.Left);
        }
        void DoBottomRightDragAction()
        {
            _controlVM.Height = _originalControlDimensions.Height - (_originalHandleLocation.Y - VM.Top);
            _controlVM.Width = _originalControlDimensions.Width - (_originalHandleLocation.X - VM.Left);
        }
        void DoBottomDragAction()
        {
            _controlVM.Height = _originalControlDimensions.Height - (_originalHandleLocation.Y - VM.Top);
        }
        void DoBottomLeftDragAction()
        {
            _controlVM.Left = VM.Left + 10;
            _controlVM.Width = _originalControlDimensions.Width + _originalControlDimensions.Left - VM.Left -10;
            _controlVM.Height = _originalControlDimensions.Height - (_originalHandleLocation.Y - VM.Top);
        }
        void DoLeftDragAction()
        {
            _controlVM.Left = VM.Left + 10;
            _controlVM.Width = _originalControlDimensions.Width + _originalControlDimensions.Left - VM.Left - 10;
        }
        #endregion

        #region IDraggable Members

        public FrameworkElement DraggableElement
        {
            get { return this; }
        }

        public bool DragEnabled
        {
            get { return true; ; }
        }

        public void OnLocationChanged()
        {
        }

        public void OnDragging()
        {
           if (_dragAction != null) _dragAction();
        }

        public void OnDragStarted()
        {
            _isDragging = true;
            UpdateOriginalDimensions();

        }

        public void OnDragEnded()
        {
            _isDragging = false;
        }

        #endregion

        #region IXamlaElement Members

        public UserControl Propertyview
        {
            get { throw new NotImplementedException(); }
        }

        public string ControlName
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public FrameworkElementViewModel ViewModel
        {
            get { return VM; }
        }

        public UserControl MenuButton
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public PlaneProjection ElementProjection
        {
            get { throw new NotImplementedException(); }
        }

        #endregion
    }

    public enum ControlHandleTypes
    {
        TopLeft = 1,
        Top,
        TopRight,
        Right,
        BottomRight,
        Bottom,
        BottomLeft,
        Left
    }
}
